package org.study.minio.boot.util;

import com.alibaba.fastjson2.JSON;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.*;
import com.amazonaws.util.IOUtils;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.study.minio.boot.config.AwsProperties;

import java.io.*;
import java.net.URL;
import java.util.*;

/**
 * AWS工具类
 *
 * @author doveylovey
 * @version v1.0.0
 * @email 1135782208@qq.com
 * @date 2023年11月25日
 */
@Slf4j
@UtilityClass
public class AwsUtils {
    private AwsProperties awsProperties;
    private AmazonS3 amazonS3;

    public void init(AwsProperties awsProperties, AmazonS3 amazonS3) {
        AwsUtils.awsProperties = awsProperties;
        AwsUtils.amazonS3 = amazonS3;
    }

    /**
     * 判断Bucket是否存在：true-存在、false-不存在
     *
     * @param bucketName 桶名
     */
    public boolean bucketExists(String bucketName) {
        return amazonS3.doesBucketExistV2(bucketName);
    }

    /**
     * 创建桶
     *
     * @param bucketName 桶名
     */
    public boolean createBucket(String bucketName) {
        if (bucketExists(bucketName)) {
            return true;
        } else {
            Bucket bucket = amazonS3.createBucket(bucketName);
            log.info("[Aws工具类]创建bucket={}成功", bucketName, JSON.toJSONString(bucket));
            return true;
        }
    }

    /**
     * 获取Bucket的策略
     *
     * @param bucketName 桶名
     */
    public String getBucketPolicy(String bucketName) {
        if (!bucketExists(bucketName)) {
            return null;
        }
        BucketPolicy bucketPolicy = amazonS3.getBucketPolicy(bucketName);
        String policyText = bucketPolicy.getPolicyText();
        return policyText;
    }

    /**
     * 获取所有Bucket列表
     */
    public List<Bucket> getAllBuckets() {
        return amazonS3.listBuckets();
    }

    /**
     * 根据bucketName获取其相关信息
     *
     * @param bucketName 桶名
     */
    public Optional<Bucket> getBucket(String bucketName) {
        if (!bucketExists(bucketName)) {
            return Optional.empty();
        }
        return getAllBuckets().stream().filter(b -> b.getName().equals(bucketName)).findFirst();
    }

    /**
     * 根据bucketName删除Bucket：true-删除成功、false-删除失败
     *
     * @param bucketName 桶名
     */
    public void removeBucket(String bucketName) {
        if (!bucketExists(bucketName)) {
            return;
        }
        amazonS3.deleteBucket(bucketName);
    }

    /**
     * 根据文件前置查询文件
     *
     * @param bucketName bucket名称
     * @param prefix     前缀
     * @param recursive  是否递归查询
     * @return S3ObjectSummary 列表
     */
    public List<S3ObjectSummary> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {
        ObjectListing objectListing = amazonS3.listObjects(bucketName, prefix);
        return new ArrayList<>(objectListing.getObjectSummaries());
    }

    /**
     * 获取文件外链
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @param expires    过期时间，<=7
     * @return url
     */
    public String getObjectURL(String bucketName, String objectName, Integer expires) {
        Date date = new Date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, expires);
        URL url = amazonS3.generatePresignedUrl(bucketName, objectName, calendar.getTime());
        return url.toString();
    }

    /**
     * 获取文件
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @return 二进制流
     */
    public S3Object getObject(String bucketName, String objectName) {
        return amazonS3.getObject(bucketName, objectName);
    }

    /**
     * 上传文件
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @param stream     文件流
     * @throws IOException
     */
    public String putObject(String bucketName, String objectName, InputStream stream) throws IOException {
        String url = putObject(bucketName, objectName, stream, (long) stream.available(), "application/octet-stream");
        return url;
    }

    /**
     * 上传文件
     *
     * @param bucketName  bucket名称
     * @param objectName  文件名称
     * @param stream      文件流
     * @param size        大小
     * @param contextType 类型
     * @throws IOException
     */
    public String putObject(String bucketName, String objectName, InputStream stream, long size, String contextType) throws IOException {
        // String fileName = getFileName(objectName);
        byte[] bytes = IOUtils.toByteArray(stream);
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(size);
        objectMetadata.setContentType(contextType);
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        // 上传
        PutObjectResult putObjectResult = amazonS3.putObject(bucketName, objectName, byteArrayInputStream, objectMetadata);
        String url = awsProperties.getEndpoint() + "/" + bucketName + "/" + objectName;
        return url;
    }

    /**
     * 获取文件信息
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     */
    public S3Object getObjectInfo(String bucketName, String objectName) {
        return amazonS3.getObject(bucketName, objectName);
    }

    /**
     * 删除文件
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     */
    public void removeObject(String bucketName, String objectName) {
        amazonS3.deleteObject(bucketName, objectName);
    }
}
